home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 32 / Amiga Format AFCD32 (Nov 1998, Issue 117).iso / -seriously_amiga- / programming / c / mesa-2.6 / src / vbrender.c < prev   
C/C++ Source or Header  |  1998-08-10  |  39KB  |  1,259 lines

  1. /* $Id: vbrender.c,v 1.21 1998/01/18 15:04:48 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.6
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * vbrender.c
  26.  *
  27.  * Modified  27 Jun 1998
  28.  * by Jarno van der Linden
  29.  * jarno@kcbbs.gen.nz
  30.  *
  31.  * Based on vbrender.c ver 1.21
  32.  * Some minor changes to work around SAS/C 6.59 optimizer bug
  33.  *
  34.  */
  35.  
  36.  
  37. /*
  38.  * Render points, lines, and polygons.  The only entry point to this
  39.  * file is the gl_render_vb() function.  This function is called after
  40.  * the vertex buffer has filled up or glEnd() has been called.
  41.  *
  42.  * This file basically only makes calls to the clipping functions and
  43.  * the point, line and triangle rasterizers via the function pointers.
  44.  *    context->Driver.PointsFunc()
  45.  *    context->Driver.LineFunc()
  46.  *    context->Driver.TriangleFunc()
  47.  */
  48.  
  49.  
  50. #ifdef PC_HEADER
  51. #include "all.h"
  52. #else
  53. #include "clip.h"
  54. #include "context.h"
  55. #include "light.h"
  56. #include "macros.h"
  57. #include "matrix.h"
  58. #include "pb.h"
  59. #include "types.h"
  60. #include "vb.h"
  61. #include "vbrender.h"
  62. #include "xform.h"
  63. #endif
  64.  
  65.  
  66. /*
  67.  * This file implements rendering of points, lines and polygons defined by
  68.  * vertices in the vertex buffer.
  69.  */
  70.  
  71.  
  72.  
  73. #ifdef PROFILE
  74. #  define START_PROFILE                \
  75.     {                    \
  76.        GLdouble t0 = gl_time();
  77.  
  78. #  define END_PROFILE( TIMER, COUNTER, INCR )    \
  79.        TIMER += (gl_time() - t0);        \
  80.        COUNTER += INCR;            \
  81.     }
  82. #else
  83. #  define START_PROFILE
  84. #  define END_PROFILE( TIMER, COUNTER, INCR )
  85. #endif
  86.  
  87.  
  88.  
  89.  
  90. /*
  91.  * Render a line segment from VB[v1] to VB[v2] when either one or both
  92.  * endpoints must be clipped.
  93.  */
  94. static void render_clipped_line( GLcontext *ctx, GLuint v1, GLuint v2 )
  95. {
  96.    GLfloat ndc_x, ndc_y, ndc_z;
  97.    GLuint provoking_vertex;
  98.    struct vertex_buffer *VB = ctx->VB;
  99.  
  100.    /* which vertex dictates the color when flat shading: */
  101.    provoking_vertex = v2;
  102.  
  103.    /*
  104.     * Clipping may introduce new vertices.  New vertices will be stored
  105.     * in the vertex buffer arrays starting with location VB->Free.  After
  106.     * we've rendered the line, these extra vertices can be overwritten.
  107.     */
  108.    VB->Free = VB_MAX;
  109.  
  110.    /* Clip against user clipping planes */
  111.    if (ctx->Transform.AnyClip) {
  112.       GLuint orig_v1 = v1, orig_v2 = v2;
  113.       if (gl_userclip_line( ctx, &v1, &v2 )==0)
  114.     return;
  115.       /* Apply projection matrix:  clip = Proj * eye */
  116.       if (v1!=orig_v1) {
  117.          TRANSFORM_POINT( VB->Clip[v1], ctx->ProjectionMatrix, VB->Eye[v1] );
  118.       }
  119.       if (v2!=orig_v2) {
  120.          TRANSFORM_POINT( VB->Clip[v2], ctx->ProjectionMatrix, VB->Eye[v2] );
  121.       }
  122.    }
  123.  
  124.    /* Clip against view volume */
  125.    if (gl_viewclip_line( ctx, &v1, &v2 )==0)
  126.       return;
  127.  
  128.    /* Transform from clip coords to ndc:  ndc = clip / W */
  129.    if (VB->Clip[v1][3] != 0.0F) {
  130.       GLfloat wInv = 1.0F / VB->Clip[v1][3];
  131.       ndc_x = VB->Clip[v1][0] * wInv;
  132.       ndc_y = VB->Clip[v1][1] * wInv;
  133.       ndc_z = VB->Clip[v1][2] * wInv;
  134.    }
  135.    else {
  136.       /* Can't divide by zero, so... */
  137.       ndc_x = ndc_y = ndc_z = 0.0F;
  138.    }
  139.  
  140.    /* Map ndc coord to window coords. */
  141.    VB->Win[v1][0] = ndc_x * ctx->Viewport.Sx + ctx->Viewport.Tx;
  142.    VB->Win[v1][1] = ndc_y * ctx->Viewport.Sy + ctx->Viewport.Ty;
  143.    VB->Win[v1][2] = ndc_z * ctx->Viewport.Sz + ctx->Viewport.Tz;
  144.  
  145.    /* Transform from clip coords to ndc:  ndc = clip / W */
  146.    if (VB->Clip[v2][3] != 0.0F) {
  147.       GLfloat wInv = 1.0F / VB->Clip[v2][3];
  148.       ndc_x = VB->Clip[v2][0] * wInv;
  149.       ndc_y = VB->Clip[v2][1] * wInv;
  150.       ndc_z = VB->Clip[v2][2] * wInv;
  151.    }
  152.    else {
  153.       /* Can't divide by zero, so... */
  154.       ndc_x = ndc_y = ndc_z = 0.0F;
  155.    }
  156.  
  157.    /* Map ndc coord to window coords. */
  158.    VB->Win[v2][0] = ndc_x * ctx->Viewport.Sx + ctx->Viewport.Tx;
  159.    VB->Win[v2][1] = ndc_y * ctx->Viewport.Sy + ctx->Viewport.Ty;
  160.    VB->Win[v2][2] = ndc_z * ctx->Viewport.Sz + ctx->Viewport.Tz;
  161.  
  162.    if (ctx->Driver.RasterSetup) {
  163.       /* Device driver rasterization setup */
  164.       (*ctx->Driver.RasterSetup)( ctx, v1, v1+1 );
  165.       (*ctx->Driver.RasterSetup)( ctx, v2, v2+1 );
  166.    }
  167.  
  168.    START_PROFILE
  169.    (*ctx->Driver.LineFunc)( ctx, v1, v2, provoking_vertex );
  170.    END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  171. }
  172.  
  173.  
  174.  
  175. /*
  176.  * Compute Z offsets for a polygon with plane defined by (A,B,C,D)
  177.  * D is not needed.
  178.  */
  179. static void offset_polygon( GLcontext *ctx, GLfloat a, GLfloat b, GLfloat c )
  180. {
  181.    GLfloat ac, bc, m;
  182.    GLfloat offset;
  183.  
  184.    if (c<0.001F && c>-0.001F) {
  185.       /* to prevent underflow problems */
  186.       offset = 0.0F;
  187.    }
  188.    else {
  189.       ac = a / c;
  190.       bc = b / c;
  191.       if (ac<0.0F)  ac = -ac;
  192.       if (bc<0.0F)  bc = -bc;
  193.       m = MAX2( ac, bc );
  194.       /* m = sqrt( ac*ac + bc*bc ); */
  195.  
  196.       offset = m * ctx->Polygon.OffsetFactor + ctx->Polygon.OffsetUnits;
  197.    }
  198.  
  199.    ctx->PointZoffset   = ctx->Polygon.OffsetPoint ? offset : 0.0F;
  200.    ctx->LineZoffset    = ctx->Polygon.OffsetLine  ? offset : 0.0F;
  201.    ctx->PolygonZoffset = ctx->Polygon.OffsetFill  ? offset : 0.0F;
  202. }
  203.  
  204.  
  205.  
  206. /*
  207.  * When glPolygonMode() is used to specify that the front/back rendering
  208.  * mode for polygons is not GL_FILL we end up calling this function.
  209.  */
  210. static void unfilled_polygon( GLcontext *ctx,
  211.                               GLuint n, GLuint vlist[],
  212.                               GLuint pv, GLuint facing )
  213. {
  214.    GLenum mode = facing ? ctx->Polygon.BackMode : ctx->Polygon.FrontMode;
  215.    struct vertex_buffer *VB = ctx->VB;
  216.  
  217.    if (mode==GL_POINT) {
  218.       GLint i, j;
  219.       GLboolean edge;
  220.  
  221.       if (   ctx->Primitive==GL_TRIANGLES
  222.           || ctx->Primitive==GL_QUADS
  223.           || ctx->Primitive==GL_POLYGON) {
  224.          edge = GL_FALSE;
  225.       }
  226.       else {
  227.          edge = GL_TRUE;
  228.       }
  229.  
  230.       for (i=0;i<n;i++) {
  231.          j = vlist[i];
  232.          if (edge || VB->Edgeflag[j]) {
  233.             (*ctx->Driver.PointsFunc)( ctx, j, j );
  234.          }
  235.       }
  236.    }
  237.    else if (mode==GL_LINE) {
  238.       GLuint i, j0, j1;
  239.       GLboolean edge;
  240.  
  241.       ctx->StippleCounter = 0;
  242.  
  243.       if (   ctx->Primitive==GL_TRIANGLES
  244.           || ctx->Primitive==GL_QUADS
  245.           || ctx->Primitive==GL_POLYGON) {
  246.          edge = GL_FALSE;
  247.       }
  248.       else {
  249.          edge = GL_TRUE;
  250.       }
  251.  
  252.       /* draw the edges */
  253.       for (i=0;i<n;i++) {
  254.          j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  255.          j1 = vlist[i];
  256.          if (edge || VB->Edgeflag[j0]) {
  257.             START_PROFILE
  258.             (*ctx->Driver.LineFunc)( ctx, j0, j1, pv );
  259.             END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  260.          }
  261.       }
  262.    }
  263.    else {
  264.       /* Fill the polygon */
  265.       GLuint j0, i, j;
  266.       j0 = vlist[0];
  267.       for (i=2;i<n;i++) {
  268.          j = i-1;
  269.          START_PROFILE
  270.          (*ctx->Driver.TriangleFunc)( ctx, j0, vlist[j], vlist[j+1], pv );
  271.          END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  272.       }
  273.    }
  274. }
  275.  
  276.  
  277. /*
  278.  * Compute signed area of the n-sided polgyon specified by vertices vb->Win[]
  279.  * and vertex list vlist[].
  280.  * A clockwise polygon will return a negative area.
  281.  * A counter-clockwise polygon will return a positive area.
  282.  */
  283. static GLfloat polygon_area( const struct vertex_buffer *vb,
  284.                              GLuint n, const GLuint vlist[] )
  285. {
  286.    GLfloat area = 0.0F;
  287.    GLint i;
  288.    for (i=0;i<n;i++) {
  289.       /* area = sum of trapezoids */
  290.       GLuint j0 = vlist[i];
  291.       GLuint j1 = vlist[(i+1)%n];
  292.       GLfloat x0 = vb->Win[j0][0];
  293.       GLfloat y0 = vb->Win[j0][1];
  294.       GLfloat x1 = vb->Win[j1][0];
  295.       GLfloat y1 = vb->Win[j1][1];
  296.       GLfloat trapArea = (x0-x1)*(y0+y1);  /* Note: no divide by two here! */
  297.       area += trapArea;
  298.    }
  299.    return area * 0.5F;     /* divide by two now! */
  300. }
  301.  
  302.  
  303. /*
  304.  * Render a polygon in which doesn't have to be clipped.
  305.  * Input:  n - number of vertices
  306.  *         vlist - list of vertices in the polygon.
  307.  */
  308. static void render_polygon( GLcontext *ctx, GLuint n, GLuint vlist[] )
  309. {
  310.    struct vertex_buffer *VB = ctx->VB;
  311.    GLuint pv;
  312.  
  313.    /* which vertex dictates the color when flat shading: */
  314.    pv = (ctx->Primitive==GL_POLYGON) ? vlist[0] : vlist[n-1];
  315.  
  316.    /* Compute orientation of polygon, do cull test, offset, etc */
  317.    {
  318.       GLuint facing;   /* 0=front, 1=back */
  319.       GLfloat area = polygon_area( VB, n, vlist );
  320.  
  321.       if (area==0.0F) {
  322.          /* polygon has zero area, don't draw it */
  323.          return;
  324.       }
  325.  
  326.       facing = (area<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW);
  327.  
  328.       if ((facing+1) & ctx->Polygon.CullBits) {
  329.          return;   /* culled */
  330.       }
  331.  
  332.       if (ctx->Polygon.OffsetAny) {
  333.          /* compute plane equation of polygon, apply offset */
  334.          GLuint j0 = vlist[0];
  335.          GLuint j1 = vlist[1];
  336.          GLuint j2 = vlist[2];
  337.          GLuint j3 = vlist[ (n==3) ? 0 : 3 ];
  338.          GLfloat ex = VB->Win[j1][0] - VB->Win[j3][0];
  339.          GLfloat ey = VB->Win[j1][1] - VB->Win[j3][1];
  340.          GLfloat ez = VB->Win[j1][2] - VB->Win[j3][2];
  341.          GLfloat fx = VB->Win[j2][0] - VB->Win[j0][0];
  342.          GLfloat fy = VB->Win[j2][1] - VB->Win[j0][1];
  343.          GLfloat fz = VB->Win[j2][2] - VB->Win[j0][2];
  344.          GLfloat a = ey*fz-ez*fy;
  345.          GLfloat b = ez*fx-ex*fz;
  346.          GLfloat c = ex*fy-ey*fx;
  347.          offset_polygon( ctx, a, b, c );
  348.       }
  349.  
  350.       if (ctx->LightTwoSide) {
  351.          if (facing==1) {
  352.             /* use back color or index */
  353.             VB->Color = VB->Bcolor;
  354.             VB->Index = VB->Bindex;
  355.          }
  356.          else {
  357.             /* use front color or index */
  358.             VB->Color = VB->Fcolor;
  359.             VB->Index = VB->Findex;
  360.          }
  361.       }
  362.  
  363.       /* Render the polygon! */
  364.       if (ctx->Polygon.Unfilled) {
  365.          unfilled_polygon( ctx, n, vlist, pv, facing );
  366.       }
  367.       else {
  368.          /* Draw filled polygon as a triangle fan */
  369.          GLint i,j;
  370.          GLuint j0 = vlist[0];
  371.          for (i=2;i<n;i++) {
  372.             j = i-1;
  373.             START_PROFILE
  374.             (*ctx->Driver.TriangleFunc)( ctx, j0, vlist[j], vlist[j+1], pv );
  375.             END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  376.          }
  377.       }
  378.    }
  379. }
  380.  
  381.  
  382.  
  383. /*
  384.  * Render a polygon in which at least one vertex has to be clipped.
  385.  * Input:  n - number of vertices
  386.  *         vlist - list of vertices in the polygon.
  387.  *                 CCW order = front facing.
  388.  */
  389. static void render_clipped_polygon( GLcontext *ctx, GLuint n, GLuint vlist[] )
  390. {
  391.    GLuint pv;
  392.    struct vertex_buffer *VB = ctx->VB;
  393.    GLfloat (*win)[3] = VB->Win;
  394.  
  395.    /* which vertex dictates the color when flat shading: */
  396.    pv = (ctx->Primitive==GL_POLYGON) ? vlist[0] : vlist[n-1];
  397.  
  398.    /*
  399.     * Clipping may introduce new vertices.  New vertices will be stored
  400.     * in the vertex buffer arrays starting with location VB->Free.  After
  401.     * we've rendered the polygon, these extra vertices can be overwritten.
  402.     */
  403.    VB->Free = VB_MAX;
  404.  
  405.    /* Clip against user clipping planes in eye coord space. */
  406.    if (ctx->Transform.AnyClip) {
  407.       GLfloat *proj = ctx->ProjectionMatrix;
  408.       GLuint i;
  409.       n = gl_userclip_polygon( ctx, n, vlist );
  410.       if (n<3)
  411.          return;
  412.       /* Transform vertices from eye to clip coordinates:  clip = Proj * eye */
  413.       for (i=0;i<n;i++) {
  414.          GLuint j = vlist[i];
  415.          TRANSFORM_POINT( VB->Clip[j], proj, VB->Eye[j] );
  416.       }
  417.    }
  418.  
  419.    /* Clip against view volume in clip coord space */
  420.    n = gl_viewclip_polygon( ctx, n, vlist );
  421.    if (n<3)
  422.       return;
  423.  
  424.    /* Transform new vertices from clip to ndc to window coords.    */
  425.    /* ndc = clip / W    window = viewport_mapping(ndc)             */
  426.    /* Note that window Z values are scaled to the range of integer */
  427.    /* depth buffer values.                                         */
  428.    {
  429.       GLfloat sx = ctx->Viewport.Sx;
  430.       GLfloat tx = ctx->Viewport.Tx;
  431.       GLfloat sy = ctx->Viewport.Sy;
  432.       GLfloat ty = ctx->Viewport.Ty;
  433.       GLfloat sz = ctx->Viewport.Sz;
  434.       GLfloat tz = ctx->Viewport.Tz;
  435.       GLuint i;
  436.       /* Only need to compute window coords for new vertices */
  437.       for (i=VB_MAX; i<VB->Free; i++) {
  438.          if (VB->Clip[i][3] != 0.0F) {
  439.             GLfloat wInv = 1.0F / VB->Clip[i][3];
  440.             win[i][0] = VB->Clip[i][0] * wInv * sx + tx;
  441.             win[i][1] = VB->Clip[i][1] * wInv * sy + ty;
  442.             win[i][2] = VB->Clip[i][2] * wInv * sz + tz;
  443.          }
  444.          else {
  445.             /* Can't divide by zero, so... */
  446.             win[i][0] = win[i][1] = win[i][2] = 0.0F;
  447.          }
  448.       }
  449.       if (ctx->Driver.RasterSetup && (VB->Free > VB_MAX)) {
  450.          /* Device driver raster setup for newly introduced vertices */
  451.          (*ctx->Driver.RasterSetup)(ctx, VB_MAX, VB->Free);
  452.       }
  453.  
  454. #ifdef DEBUG
  455.       {
  456.          int i, j;
  457.          for (i=0;i<n;i++) {
  458.             j = vlist[i];
  459.             if (VB->ClipMask[j]) {
  460.                /* Uh oh!  There should be no clip bits set in final polygon! */
  461.                int k, l;
  462.                printf("CLIPMASK %d %d %02x\n", i, j, VB->ClipMask[j]);
  463.                printf("%f %f %f %f\n", VB->Eye[j][0], VB->Eye[j][1],
  464.                       VB->Eye[j][2], VB->Eye[j][3]);
  465.                printf("%f %f %f %f\n", VB->Clip[j][0], VB->Clip[j][1],
  466.                       VB->Clip[j][2], VB->Clip[j][3]);
  467.                for (k=0;k<n;k++) {
  468.                   l = vlist[k];
  469.                   printf("%d %d %02x\n", k, l, VB->ClipMask[l]);
  470.                }
  471.             }
  472.          }
  473.       }
  474. #endif
  475.    }
  476.  
  477.    /* Compute orientation of polygon, do cull test, offset, etc */
  478.    {
  479.       GLuint facing;   /* 0=front, 1=back */
  480.       GLfloat area = polygon_area( VB, n, vlist );
  481.  
  482.       if (area==0.0F) {
  483.          /* polygon has zero area, don't draw it */
  484.          return;
  485.       }
  486.  
  487.       facing = (area<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW);
  488.  
  489.       if ((facing+1) & ctx->Polygon.CullBits) {
  490.          return;   /* culled */
  491.       }
  492.  
  493.       if (ctx->Polygon.OffsetAny) {
  494.          /* compute plane equation of polygon, apply offset */
  495.          GLuint j0 = vlist[0];
  496.          GLuint j1 = vlist[1];
  497.          GLuint j2 = vlist[2];
  498.          GLuint j3 = vlist[ (n==3) ? 0 : 3 ];
  499.          GLfloat ex = win[j1][0] - win[j3][0];
  500.          GLfloat ey = win[j1][1] - win[j3][1];
  501.          GLfloat ez = win[j1][2] - win[j3][2];
  502.          GLfloat fx = win[j2][0] - win[j0][0];
  503.          GLfloat fy = win[j2][1] - win[j0][1];
  504.          GLfloat fz = win[j2][2] - win[j0][2];
  505.          GLfloat a = ey*fz-ez*fy;
  506.          GLfloat b = ez*fx-ex*fz;
  507.          GLfloat c = ex*fy-ey*fx;
  508.          offset_polygon( ctx, a, b, c );
  509.       }
  510.  
  511.       if (ctx->LightTwoSide) {
  512.          if (facing==1) {
  513.             /* use back color or index */
  514.             VB->Color = VB->Bcolor;
  515.             VB->Index = VB->Bindex;
  516.          }
  517.          else {
  518.             /* use front color or index */
  519.             VB->Color = VB->Fcolor;
  520.             VB->Index = VB->Findex;
  521.          }
  522.       }
  523.  
  524.       /* Render the polygon! */
  525.       if (ctx->Polygon.Unfilled) {
  526.          unfilled_polygon( ctx, n, vlist, pv, facing );
  527.       }
  528.       else {
  529.          /* Draw filled polygon as a triangle fan */
  530.          GLint i,j;
  531.          GLuint j0 = vlist[0];
  532.          for (i=2;i<n;i++) {
  533.             j = i-1;
  534.             START_PROFILE
  535.             (*ctx->Driver.TriangleFunc)( ctx, j0, vlist[j], vlist[j+1], pv );
  536.             END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  537.          }
  538.       }
  539.    }
  540. }
  541.  
  542.  
  543.  
  544. /*
  545.  * Render an un-clipped triangle.
  546.  * v0, v1, v2 - vertex indexes.  CCW order = front facing
  547.  * pv - provoking vertex
  548.  */
  549. static void render_triangle( GLcontext *ctx,
  550.                              GLuint v0, GLuint v1, GLuint v2, GLuint pv )
  551. {
  552.    struct vertex_buffer *VB = ctx->VB;
  553.    GLfloat ex, ey, fx, fy, c;
  554.    GLuint facing;  /* 0=front, 1=back */
  555.    GLfloat (*win)[3] = VB->Win;
  556.  
  557.    /* Compute orientation of triangle */
  558.    ex = win[v1][0] - win[v0][0];
  559.    ey = win[v1][1] - win[v0][1];
  560.    fx = win[v2][0] - win[v0][0];
  561.    fy = win[v2][1] - win[v0][1];
  562.    c = ex*fy-ey*fx;
  563.  
  564.    if (c==0.0F) {
  565.       /* polygon is perpindicular to view plane, don't draw it */
  566.       return;
  567.    }
  568.  
  569.    facing = (c<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW);
  570.  
  571.    if ((facing+1) & ctx->Polygon.CullBits) {
  572.       return;   /* culled */
  573.    }
  574.  
  575.    if (ctx->Polygon.OffsetAny) {
  576.       /* finish computing plane equation of polygon, compute offset */
  577.       GLfloat fz = win[v2][2] - win[v0][2];
  578.       GLfloat ez = win[v1][2] - win[v0][2];
  579.       GLfloat a = ey*fz-ez*fy;
  580.       GLfloat b = ez*fx-ex*fz;
  581.       offset_polygon( ctx, a, b, c );
  582.    }
  583.  
  584.    if (ctx->LightTwoSide) {
  585.       if (facing==1) {
  586.          /* use back color or index */
  587.          VB->Color = VB->Bcolor;
  588.          VB->Index = VB->Bindex;
  589.       }
  590.       else {
  591.          /* use front color or index */
  592.          VB->Color = VB->Fcolor;
  593.          VB->Index = VB->Findex;
  594.       }
  595.    }
  596.  
  597.    if (ctx->Polygon.Unfilled) {
  598.       GLuint vlist[3];
  599.       vlist[0] = v0;
  600.       vlist[1] = v1;
  601.       vlist[2] = v2;
  602.       unfilled_polygon( ctx, 3, vlist, pv, facing );
  603.    }
  604.    else {
  605.       START_PROFILE
  606.       (*ctx->Driver.TriangleFunc)( ctx, v0, v1, v2, pv );
  607.       END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  608.    }
  609. }
  610.  
  611.  
  612.  
  613. /*
  614.  * Render an un-clipped quadrilateral.
  615.  * v0, v1, v2, v3 : CCW order = front facing
  616.  * pv - provoking vertex
  617.  */
  618. static void render_quad( GLcontext *ctx, GLuint v0, GLuint v1,
  619.                          GLuint v2, GLuint v3, GLuint pv )
  620. {
  621.    struct vertex_buffer *VB = ctx->VB;
  622.    GLfloat ex, ey, fx, fy, c;
  623.    GLuint facing;  /* 0=front, 1=back */
  624.    GLfloat (*win)[3] = VB->Win;
  625.  
  626.    /* Compute polygon orientation */
  627.    ex = win[v2][0] - win[v0][0];
  628.    ey = win[v2][1] - win[v0][1];
  629.    fx = win[v3][0] - win[v1][0];
  630.    fy = win[v3][1] - win[v1][1];
  631.    c = ex*fy-ey*fx;
  632.  
  633.    if (c==0.0F) {
  634.       /* polygon is perpindicular to view plane, don't draw it */
  635.       return;
  636.    }
  637.  
  638.    facing = (c<0.0F) ^ (ctx->Polygon.FrontFace==GL_CW);
  639.  
  640.    if ((facing+1) & ctx->Polygon.CullBits) {
  641.       return;   /* culled */
  642.    }
  643.  
  644.    if (ctx->Polygon.OffsetAny) {
  645.       /* finish computing plane equation of polygon, compute offset */
  646.       GLfloat ez = win[v2][2] - win[v0][2];
  647.       GLfloat fz = win[v3][2] - win[v1][2];
  648.       GLfloat a = ey*fz-ez*fy;
  649.       GLfloat b = ez*fx-ex*fz;
  650.       offset_polygon( ctx, a, b, c );
  651.    }
  652.  
  653.    if (ctx->LightTwoSide) {
  654.       if (facing==1) {
  655.          /* use back color or index */
  656.          VB->Color = VB->Bcolor;
  657.          VB->Index = VB->Bindex;
  658.       }
  659.       else {
  660.          /* use front color or index */
  661.          VB->Color = VB->Fcolor;
  662.          VB->Index = VB->Findex;
  663.       }
  664.    }
  665.  
  666.    /* Render the quad! */
  667.    if (ctx->Polygon.Unfilled) {
  668.       GLuint vlist[4];
  669.       vlist[0] = v0;
  670.       vlist[1] = v1;
  671.       vlist[2] = v2;
  672.       vlist[3] = v3;
  673.       unfilled_polygon( ctx, 4, vlist, pv, facing );
  674.    }
  675.    else {
  676.       START_PROFILE
  677.       (*ctx->Driver.QuadFunc)( ctx, v0, v1, v2, v3, pv );
  678.       END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  679.    }
  680. }
  681.  
  682.  
  683.  
  684. /*
  685.  * When the vertex buffer is full, we transform/render it.  Sometimes we
  686.  * have to copy the last vertex (or two) to the front of the vertex list
  687.  * to "continue" the primitive.  For example:  line or triangle strips.
  688.  * This function is a helper for that.
  689.  */
  690. static void copy_vertex( struct vertex_buffer *vb, GLuint dst, GLuint src )
  691. {
  692.    COPY_4V( vb->Clip[dst], vb->Clip[src] );
  693.    COPY_4V( vb->Eye[dst], vb->Eye[src] );
  694.    COPY_3V( vb->Win[dst], vb->Win[src] );
  695.    COPY_4V( vb->Fcolor[dst], vb->Fcolor[src] );
  696.    COPY_4V( vb->Bcolor[dst], vb->Bcolor[src] );
  697.    COPY_4V( vb->TexCoord[dst], vb->TexCoord[src] );
  698.    vb->Findex[dst] = vb->Findex[src];
  699.    vb->Bindex[dst] = vb->Bindex[src];
  700.    vb->Edgeflag[dst] = vb->Edgeflag[src];
  701.    vb->ClipMask[dst] = vb->ClipMask[src];
  702.    vb->MaterialMask[dst] = vb->MaterialMask[src];
  703.    vb->Material[dst][0] = vb->Material[src][0];
  704.    vb->Material[dst][1] = vb->Material[src][1];
  705. }
  706.  
  707.  
  708.  
  709.  
  710. /*
  711.  * Either the vertex buffer is full (VB->Count==VB_MAX) or glEnd() has been
  712.  * called.  Render the primitives defined by the vertices and reset the
  713.  * buffer.
  714.  *
  715.  * This function won't be called if the device driver implements a
  716.  * RenderVB() function.  If the device driver renders the vertex buffer
  717.  * then the driver must also call gl_reset_vb()!
  718.  *
  719.  * Input:  allDone - GL_TRUE = caller is glEnd()
  720.  *                   GL_FALSE = calling because buffer is full.
  721.  */
  722. void gl_render_vb( GLcontext *ctx, GLboolean allDone )
  723. {
  724.    struct vertex_buffer *VB = ctx->VB;
  725.    GLuint vlist[VB_SIZE];
  726.  
  727.    switch (ctx->Primitive) {
  728.       case GL_POINTS:
  729.          START_PROFILE
  730.          (*ctx->Driver.PointsFunc)( ctx, 0, VB->Count-1 );
  731.          END_PROFILE( ctx->PointTime, ctx->PointCount, VB->Count )
  732.      break;
  733.  
  734.       case GL_LINES:
  735.          if (VB->ClipOrMask) {
  736.             GLuint i;
  737.             for (i=1;i<VB->Count;i+=2) {
  738.                if (VB->ClipMask[i-1] | VB->ClipMask[i]) {
  739.                   render_clipped_line( ctx, i-1, i );
  740.                }
  741.                else {
  742.                   START_PROFILE
  743.                   (*ctx->Driver.LineFunc)( ctx, i-1, i, i );
  744.                   END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  745.                }
  746.                ctx->StippleCounter = 0;
  747.             }
  748.          }
  749.          else {
  750.             GLuint i;
  751.             for (i=1;i<VB->Count;i+=2) {
  752.                START_PROFILE
  753.                (*ctx->Driver.LineFunc)( ctx, i-1, i, i );
  754.                END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  755.                ctx->StippleCounter = 0;
  756.             }
  757.          }
  758.      break;
  759.  
  760.       case GL_LINE_STRIP:
  761.          if (VB->ClipOrMask) {
  762.             GLuint i;
  763.         for (i=1;i<VB->Count;i++) {
  764.                if (VB->ClipMask[i-1] | VB->ClipMask[i]) {
  765.                   render_clipped_line( ctx, i-1, i );
  766.                }
  767.                else {
  768.                   START_PROFILE
  769.                   (*ctx->Driver.LineFunc)( ctx, i-1, i, i );
  770.                   END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  771.                }
  772.         }
  773.          }
  774.          else {
  775.             /* no clipping needed */
  776.             GLuint i;
  777.         for (i=1;i<VB->Count;i++) {
  778.                START_PROFILE
  779.                (*ctx->Driver.LineFunc)( ctx, i-1, i, i );
  780.                END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  781.             }
  782.          }
  783.          break;
  784.  
  785.       case GL_LINE_LOOP:
  786.          {
  787.             GLuint i;
  788.             if (VB->Start==0) {
  789.                i = 1;  /* start at 0th vertex */
  790.             }
  791.             else {
  792.                i = 2;  /* skip first vertex, we're saving it until glEnd */
  793.             }
  794.             while (i<VB->Count) {
  795.                if (VB->ClipMask[i-1] | VB->ClipMask[i]) {
  796.                   render_clipped_line( ctx, i-1, i );
  797.                }
  798.                else {
  799.                   START_PROFILE
  800.                   (*ctx->Driver.LineFunc)( ctx, i-1, i, i );
  801.                   END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  802.                }
  803.                i++;
  804.             }
  805.          }
  806.          break;
  807.  
  808.       case GL_TRIANGLES:
  809.          if (VB->ClipOrMask) {
  810.             GLuint i;
  811.             for (i=2;i<VB->Count;i+=3) {
  812.                if (VB->ClipMask[i-2] & VB->ClipMask[i-1]
  813.                    & VB->ClipMask[i] & CLIP_ALL_BITS) {
  814.                   /* all points clipped by common plane */
  815.                   continue;
  816.                }
  817.                else if (VB->ClipMask[i-2] | VB->ClipMask[i-1] | VB->ClipMask[i]) {
  818.                   vlist[0] = i-2;
  819.                   vlist[1] = i-1;
  820.                   vlist[2] = i-0;
  821.                   render_clipped_polygon( ctx, 3, vlist );
  822.                }
  823.                else {
  824.                   if (ctx->DirectTriangles) {
  825.                      START_PROFILE
  826.                      (*ctx->Driver.TriangleFunc)( ctx, i-2, i-1, i, i );
  827.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  828.                   }
  829.                   else {
  830.                      render_triangle( ctx, i-2, i-1, i, i );
  831.                   }
  832.                }
  833.             }
  834.          }
  835.          else {
  836.             /* no clipping needed */
  837.             GLuint i;
  838.             if (ctx->DirectTriangles) {
  839.                for (i=2;i<VB->Count;i+=3) {
  840.                   START_PROFILE
  841.                   (*ctx->Driver.TriangleFunc)( ctx, i-2, i-1, i, i );
  842.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  843.                }
  844.             }
  845.             else {
  846.                for (i=2;i<VB->Count;i+=3) {
  847.                   render_triangle( ctx, i-2, i-1, i, i );
  848.                }
  849.             }
  850.          }
  851.      break;
  852.  
  853.       case GL_TRIANGLE_STRIP:
  854.          if (VB->ClipOrMask) {
  855.             GLuint i;
  856.             for (i=2;i<VB->Count;i++) {
  857.                if (VB->ClipMask[i-2] & VB->ClipMask[i-1]
  858.                    & VB->ClipMask[i] & CLIP_ALL_BITS) {
  859.                   /* all points clipped by common plane */
  860.                   continue;
  861.                }
  862.                else if (VB->ClipMask[i-2] | VB->ClipMask[i-1] | VB->ClipMask[i]) {
  863.                   if (i&1) {
  864.                      /* reverse vertex order */
  865.                      vlist[0] = i-1;
  866.                      vlist[1] = i-2;
  867.                      vlist[2] = i-0;
  868.                      render_clipped_polygon( ctx, 3, vlist );
  869.                   }
  870.                   else {
  871.                      vlist[0] = i-2;
  872.                      vlist[1] = i-1;
  873.                      vlist[2] = i-0;
  874.                      render_clipped_polygon( ctx, 3, vlist );
  875.                   }
  876.                }
  877.                else {
  878.                   if (ctx->DirectTriangles) {
  879.                      START_PROFILE
  880.                      (*ctx->Driver.TriangleFunc)( ctx, i-2, i-1, i, i );
  881.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  882.                   }
  883.                   else {
  884.                      if (i&1)
  885.                         render_triangle( ctx, i, i-1, i-2, i );
  886.                      else
  887.                         render_triangle( ctx, i-2, i-1, i, i );
  888.                   }
  889.                }
  890.             }
  891.          }
  892.          else {
  893.             /* no vertices were clipped */
  894.             GLuint i;
  895.             if (ctx->DirectTriangles) {
  896.                for (i=2;i<VB->Count;i++) {
  897.                   START_PROFILE
  898.                   (*ctx->Driver.TriangleFunc)( ctx, i-2, i-1, i, i );
  899.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  900.                }
  901.             }
  902.             else {
  903.                for (i=2;i<VB->Count;i++) {
  904.                   if (i&1)
  905.                      render_triangle( ctx, i, i-1, i-2, i );
  906.                   else
  907.                      render_triangle( ctx, i-2, i-1, i, i );
  908.                }
  909.             }
  910.          }
  911.      break;
  912.  
  913.       case GL_TRIANGLE_FAN:
  914.          if (VB->ClipOrMask) {
  915.             GLuint i;
  916.             for (i=2;i<VB->Count;i++) {
  917.                if (VB->ClipMask[0] & VB->ClipMask[i-1] & VB->ClipMask[i]
  918.                    & CLIP_ALL_BITS) {
  919.                   /* all points clipped by common plane */
  920.                   continue;
  921.                }
  922.                else if (VB->ClipMask[0] | VB->ClipMask[i-1] | VB->ClipMask[i]) {
  923.                   vlist[0] = 0;
  924.                   vlist[1] = i-1;
  925.                   vlist[2] = i;
  926.                   render_clipped_polygon( ctx, 3, vlist );
  927.                }
  928.                else {
  929.                   if (ctx->DirectTriangles) {
  930.                      START_PROFILE
  931.                      (*ctx->Driver.TriangleFunc)( ctx, 0, i-1, i, i );
  932.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  933.                   }
  934.                   else {
  935.                      render_triangle( ctx, 0, i-1, i, i );
  936.                   }
  937.                }
  938.             }
  939.          }
  940.          else {
  941.             /* no clipping needed */
  942.             GLuint i;
  943.             if (ctx->DirectTriangles) {
  944.                for (i=2;i<VB->Count;i++) {
  945.                   START_PROFILE
  946.                   (*ctx->Driver.TriangleFunc)( ctx, 0, i-1, i, i );
  947.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  948.                }
  949.             }
  950.             else {
  951.                for (i=2;i<VB->Count;i++) {
  952.                   render_triangle( ctx, 0, i-1, i, i );
  953.                }
  954.             }
  955.          }
  956.      break;
  957.  
  958.       case GL_QUADS:
  959.          if (VB->ClipOrMask) {
  960.             GLuint i;
  961.             for (i=3;i<VB->Count;i+=4) {
  962.                if (VB->ClipMask[i-3] & VB->ClipMask[i-2]
  963.                    & VB->ClipMask[i-1] & VB->ClipMask[i] & CLIP_ALL_BITS) {
  964.                   /* all points clipped by common plane */
  965.                   continue;
  966.                }
  967.                else if (VB->ClipMask[i-3] | VB->ClipMask[i-2]
  968.                         | VB->ClipMask[i-1] | VB->ClipMask[i]) {
  969.                   vlist[0] = i-3;
  970.                   vlist[1] = i-2;
  971.                   vlist[2] = i-1;
  972.                   vlist[3] = i-0;
  973.                   render_clipped_polygon( ctx, 4, vlist );
  974.                }
  975.                else {
  976.                   if (ctx->DirectTriangles) {
  977.                      START_PROFILE
  978.                      (*ctx->Driver.QuadFunc)( ctx, i-3, i-2, i-1, i, i );
  979.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  980.                   }
  981.                   else {
  982.                      render_quad( ctx, i-3, i-2, i-1, i, i );
  983.                   }
  984.                }
  985.             }
  986.          }
  987.          else {
  988.             /* no vertices were clipped */
  989.             GLuint i;
  990.             if (ctx->DirectTriangles) {
  991.                for (i=3;i<VB->Count;i+=4) {
  992.                   START_PROFILE
  993.                   (*ctx->Driver.QuadFunc)( ctx, i-3, i-2, i-1, i, i );
  994.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  995.                }
  996.             }
  997.             else {
  998.                for (i=3;i<VB->Count;i+=4) {
  999.                   render_quad( ctx, i-3, i-2, i-1, i, i );
  1000.                }
  1001.             }
  1002.          }
  1003.      break;
  1004.  
  1005.       case GL_QUAD_STRIP:
  1006.          if (VB->ClipOrMask) {
  1007.             GLuint i;
  1008.             for (i=3;i<VB->Count;i+=2) {
  1009.                if (VB->ClipMask[i-2] & VB->ClipMask[i-3]
  1010.                    & VB->ClipMask[i-1] & VB->ClipMask[i] & CLIP_ALL_BITS) {
  1011.                   /* all points clipped by common plane */
  1012.                   continue;
  1013.                }
  1014.                else if (VB->ClipMask[i-2] | VB->ClipMask[i-3]
  1015.                         | VB->ClipMask[i-1] | VB->ClipMask[i]) {
  1016.                   vlist[0] = i-1;
  1017.                   vlist[1] = i-3;
  1018.                   vlist[2] = i-2;
  1019.                   vlist[3] = i-0;
  1020.                   render_clipped_polygon( ctx, 4, vlist );
  1021.                }
  1022.                else {
  1023.                   if (ctx->DirectTriangles) {
  1024.                      START_PROFILE
  1025.                      (*ctx->Driver.QuadFunc)( ctx, i-3, i-2, i, i-1, i );
  1026.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  1027.                   }
  1028.                   else {
  1029.                      render_quad( ctx, i-3, i-2, i, i-1, i );
  1030.                   }
  1031.                }
  1032.             }
  1033.          }
  1034.          else {
  1035.             /* no clipping needed */
  1036.             GLuint i;
  1037.             if (ctx->DirectTriangles) {
  1038.                for (i=3;i<VB->Count;i+=2) {
  1039.                   START_PROFILE
  1040.                   (*ctx->Driver.QuadFunc)( ctx, i-3, i-2, i, i-1, i );
  1041.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  1042.                }
  1043.             }
  1044.             else {
  1045.                for (i=3;i<VB->Count;i+=2) {
  1046.                   render_quad( ctx, i-3, i-2, i, i-1, i );
  1047.                }
  1048.             }
  1049.          }
  1050.      break;
  1051.  
  1052.       case GL_POLYGON:
  1053.          if (VB->Count>2) {
  1054.             if (VB->ClipAndMask & CLIP_ALL_BITS) {
  1055.                /* all points clipped by common plane, draw nothing */
  1056.                break;
  1057.             }
  1058.             if (VB->ClipOrMask) {
  1059.                /* need clipping */
  1060.                GLuint i;
  1061.                for (i=0;i<VB->Count;i++) {
  1062.                   vlist[i] = i;
  1063.                }
  1064.                render_clipped_polygon( ctx, VB->Count, vlist );
  1065.             }
  1066.             else {
  1067.                /* no clipping needed */
  1068.                static GLuint const_vlist[VB_SIZE];
  1069.                static GLboolean initFlag = GL_TRUE;
  1070.                if (initFlag) {
  1071.                   /* vertex list always the same, never changes */
  1072.                   GLuint i;
  1073.                   for (i=0;i<VB_SIZE;i++) {
  1074.                      const_vlist[i] = i;
  1075.                   }
  1076.                   initFlag = GL_FALSE;
  1077.                }
  1078.                render_polygon( ctx, VB->Count, const_vlist );
  1079.             }
  1080.          }
  1081.      break;
  1082.  
  1083.       default:
  1084.          /* should never get here */
  1085.          gl_problem( ctx, "invalid mode in gl_render_vb" );
  1086.    }
  1087.  
  1088.    gl_reset_vb( ctx, allDone );
  1089. }
  1090.  
  1091.  
  1092. #define CLIP_ALL_BITS    0x3f
  1093.  
  1094.  
  1095. /*
  1096.  * After we've rendered the primitives in the vertex buffer we call
  1097.  * this function to reset the vertex buffer.  That is, we prepare it
  1098.  * for the next batch of vertices.
  1099.  * Input:  ctx - the context
  1100.  *         allDone - GL_TRUE = glEnd() was called
  1101.  *                   GL_FALSE = buffer was filled, more vertices to come
  1102.  */
  1103. void gl_reset_vb( GLcontext *ctx, GLboolean allDone )
  1104. {
  1105.    struct vertex_buffer *VB = ctx->VB;
  1106.  
  1107.    /* save a few VB values for the end of this function */
  1108.    int oldCount = VB->Count;
  1109.    GLubyte clipOrMask = VB->ClipOrMask;
  1110.    GLboolean monoMaterial = VB->MonoMaterial;
  1111.    GLuint vertexSizeMask = VB->VertexSizeMask;
  1112.  
  1113.    /* Special case for GL_LINE_LOOP */
  1114.    if (ctx->Primitive==GL_LINE_LOOP && allDone) {
  1115.       if (VB->ClipMask[VB->Count-1] | VB->ClipMask[0]) {
  1116.          render_clipped_line( ctx, VB->Count-1, 0 );
  1117.       }
  1118.       else {
  1119.          START_PROFILE
  1120.          (*ctx->Driver.LineFunc)( ctx, VB->Count-1, 0, 0 );
  1121.          END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  1122.       }
  1123.    }
  1124.  
  1125.    if (allDone) {
  1126.       /* glEnd() was called so reset Vertex Buffer to default, empty state */
  1127.       VB->Start = VB->Count = 0;
  1128.       VB->ClipOrMask = 0;
  1129.       VB->ClipAndMask = CLIP_ALL_BITS;
  1130.       VB->MonoMaterial = GL_TRUE;
  1131.       VB->MonoNormal = GL_TRUE;
  1132.       VB->MonoColor = GL_TRUE;
  1133.       VB->VertexSizeMask = VERTEX3_BIT;
  1134.       if (VB->TexCoordSize!=2) {
  1135.          GLint i, n = VB->Count;
  1136.          for (i=0;i<n;i++) {
  1137.             VB->TexCoord[i][2] = 0.0F;
  1138.             VB->TexCoord[i][3] = 1.0F;
  1139.          }
  1140.       }
  1141.       if (ctx->Current.TexCoord[2]==0.0F && ctx->Current.TexCoord[3]==1.0F) {
  1142.          VB->TexCoordSize = 2;
  1143.       }
  1144.       else {
  1145.          VB->TexCoordSize = 4;
  1146.       }
  1147.    }
  1148.    else {
  1149.       /* The vertex buffer was filled but we didn't get a glEnd() call yet
  1150.        * have to "re-cycle" the vertex buffer.
  1151.        */
  1152.       switch (ctx->Primitive) {
  1153.          case GL_POINTS:
  1154.             ASSERT(VB->Start==0);
  1155.             VB->Start = VB->Count = 0;
  1156.             VB->ClipOrMask = 0;
  1157.             VB->ClipAndMask = CLIP_ALL_BITS;
  1158.             VB->MonoMaterial = GL_TRUE;
  1159.             VB->MonoNormal = GL_TRUE;
  1160.             break;
  1161.          case GL_LINES:
  1162.             ASSERT(VB->Start==0);
  1163.             VB->Start = VB->Count = 0;
  1164.             VB->ClipOrMask = 0;
  1165.             VB->ClipAndMask = CLIP_ALL_BITS;
  1166.             VB->MonoMaterial = GL_TRUE;
  1167.             VB->MonoNormal = GL_TRUE;
  1168.             break;
  1169.          case GL_LINE_STRIP:
  1170.             copy_vertex( VB, 0, VB->Count-1 );  /* copy last vertex to front */
  1171.             VB->Start = VB->Count = 1;
  1172.             VB->ClipOrMask = VB->ClipMask[0];
  1173.             VB->ClipAndMask = VB->ClipMask[0];
  1174.             VB->MonoMaterial = VB->MaterialMask[0] ? GL_FALSE : GL_TRUE;
  1175.             break;
  1176.          case GL_LINE_LOOP:
  1177.             ASSERT(VB->Count==VB_MAX);
  1178.             copy_vertex( VB, 1, VB_MAX-1 );
  1179.             VB->Start = VB->Count = 2;
  1180.             VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1];
  1181.             VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1];
  1182.             VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]);
  1183.             break;
  1184.          case GL_TRIANGLES:
  1185.             ASSERT(VB->Start==0);
  1186.             VB->Start = VB->Count = 0;
  1187.             VB->ClipOrMask = 0;
  1188.             VB->ClipAndMask = CLIP_ALL_BITS;
  1189.             VB->MonoMaterial = GL_TRUE;
  1190.             VB->MonoNormal = GL_TRUE;
  1191.             break;
  1192.          case GL_TRIANGLE_STRIP:
  1193.             copy_vertex( VB, 0, VB_MAX-2 );
  1194.             copy_vertex( VB, 1, VB_MAX-1 );
  1195.             VB->Start = VB->Count = 2;
  1196.             VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1];
  1197.             VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1];
  1198.             VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]);
  1199.             break;
  1200.          case GL_TRIANGLE_FAN:
  1201.             copy_vertex( VB, 1, VB_MAX-1 );
  1202.             VB->Start = VB->Count = 2;
  1203.             VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1];
  1204.             VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1];
  1205.             VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]);
  1206.             break;
  1207.          case GL_QUADS:
  1208.             ASSERT(VB->Start==0);
  1209.             VB->Start = VB->Count = 0;
  1210.             VB->ClipOrMask = 0;
  1211.             VB->ClipAndMask = CLIP_ALL_BITS;
  1212.             VB->MonoMaterial = GL_TRUE;
  1213.             VB->MonoNormal = GL_TRUE;
  1214.             break;
  1215.          case GL_QUAD_STRIP:
  1216.             copy_vertex( VB, 0, VB_MAX-2 );
  1217.             copy_vertex( VB, 1, VB_MAX-1 );
  1218.             VB->Start = VB->Count = 2;
  1219.             VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1];
  1220.             VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1];
  1221.             VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]);
  1222.             break;
  1223.          case GL_POLYGON:
  1224.             copy_vertex( VB, 1, VB_MAX-1 );
  1225.             VB->Start = VB->Count = 2;
  1226.             VB->ClipOrMask = VB->ClipMask[0] | VB->ClipMask[1];
  1227.             VB->ClipAndMask = VB->ClipMask[0] & VB->ClipMask[1];
  1228.             VB->MonoMaterial = !(VB->MaterialMask[0] | VB->MaterialMask[1]);
  1229.             break;
  1230.          default:
  1231.             /* should never get here */
  1232.             gl_problem(ctx, "Bad primitive type in gl_reset_vb()");
  1233.       }
  1234.    }
  1235.  
  1236.    if (clipOrMask) {
  1237.       /* reset clip masks to zero */
  1238.       MEMSET( VB->ClipMask + VB->Start, 0,
  1239.               (oldCount - VB->Start) * sizeof(VB->ClipMask[0]) );
  1240.    }
  1241.  
  1242.    if (!monoMaterial) {
  1243.       /* reset material masks to zero */
  1244.       MEMSET( VB->MaterialMask + VB->Start, 0,
  1245.               (oldCount - VB->Start) * sizeof(VB->MaterialMask[0]) );
  1246.       gl_update_lighting(ctx);
  1247.    }
  1248.  
  1249.    if (vertexSizeMask!=VERTEX3_BIT) {
  1250.       /* reset object W coords to one */
  1251.       GLint i, n;
  1252.       GLfloat (*obj)[4] = VB->Obj + VB->Start;
  1253.       n = oldCount - VB->Start;
  1254.       for (i=0; i<n; i++) {
  1255.          obj[i][3] = 1.0F;
  1256.       }
  1257.    }
  1258. }
  1259.